using System.Runtime.CompilerServices;
using System;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEditor;
using System.Text;

public class AndroidDebugTools : EditorWindow
{
    /// <summary>
    /// 当前编辑器窗口实例
    /// </summary>
    private static AndroidDebugTools instance;

    //以下变量在界面中配置，且会写入到Shell脚本中

    /// <summary>
    /// 启动apk的活动名
    /// </summary>
    private static string activity_name = "";

    /// <summary>
    /// apk 名称(不包含后缀)
    /// </summary>
    private static string apk_name;

    /// <summary>
    /// 包名
    /// </summary>
    private static string pkg_name;

    /// <summary>
    /// apk 打包路径
    /// </summary>
    private static string apk_path;

    /// <summary>
    /// 安装后是否自动运行apk
    /// </summary>
    private static bool auto_run;

    /// <summary>
    /// 是否自动adb调试
    /// </summary>
    private static bool auto_logcat;

    /// <summary>
    /// logcat 过滤条件
    /// </summary>
    private static string logcat_filter;

    /// <summary>
    /// adb端口号
    /// </summary>
    private static string adb_port;

    private static string TAG = "";

    //Win版本用Git运行Shell脚本
    private static string winGitBashPath = "";
    private const string defaultWinGitBashPath = "C:/Program Files/Git/git-bash.exe";

    private static Thread shellThread;

    private static Process proc;

    /// <summary>
    /// 设置配置信息
    /// </summary>
    [MenuItem("Android Tools/Config %#i")]
    static void SetConfigs()
    {
        //获取当前实例
        instance = EditorWindow.GetWindow<AndroidDebugTools>();

        GetConfig();

        instance.Show();
    }

    static string[] GetBuildScenes()
    {
        List<string> names = new List<string>();
        foreach(EditorBuildSettingsScene e in EditorBuildSettings.scenes)
        {
            if(e == null)
                continue;
            if(e.enabled)
                names.Add(e.path);
        }
        return names.ToArray();
    }

    /// <summary>
    /// 安装
    /// </summary>
    [MenuItem("Android Tools/Install #i")]
    static void Install()
    {
        RunShell(false);
    }

    /// <summary>
    /// 打包
    /// </summary>
    [MenuItem("Android Tools/Build #B")]
    static void Build()
    {
        GetConfig();

        string path = apk_path + "/" + apk_name + ".apk";

        UnityEngine.Debug.Log("打包的路径是:" + path);

        bool success = true;

        try
        {
            BuildPipeline.BuildPlayer(GetBuildScenes(), path, BuildTarget.Android, BuildOptions.None);
        }
        catch(Exception e)
        {
            UnityEngine.Debug.LogError("打包失败:" + e.ToString());
        }

        if(success)
        {
            UnityEngine.Debug.Log("Build Success");
        }
    }

    /// <summary>
    /// 打包并安装
    /// </summary>
    [MenuItem("Android Tools/BuildAndInstall %#B")]
    static void BuildAndInstall()
    {
        Build();

        RunShell(false);
    }

    [MenuItem("Android Tools/ConnectToLogcat #D")]
    static void ConnectToLogcat()
    {
        RunShell(true);
    }

    /// <summary>
    /// 用来结束adb logcat 
    /// </summary>
    [MenuItem("Android Tools/KillAdb %#k")]
    static void ExitADB()
    {
        try
        {
            if(proc != null && !proc.HasExited)
            {
                proc.CancelErrorRead();
                proc.CancelOutputRead();
                proc.Kill();
                UnityEngine.Debug.Log("kill adb");
            }
            if(shellThread != null)
            {
                shellThread.Abort();
            }
        }
        catch(Exception e)
        {
            UnityEngine.Debug.Log("e:" + e.ToString());
        }
    }

    //运行Shell脚本，win版本必须配置Git-Bash路径
    public static void RunShell(bool only_logcat = false)
    {
        if(only_logcat)
        {
            UnityEngine.Debug.Log("use shell to connect logcat");
        }
        else
        {
            UnityEngine.Debug.Log("use shell to install");
        }

        //更新Shell脚本
        UpdateShellFile(only_logcat);

        //退出Adb进程
        ExitADB();

        string filePath = GetShellFilePath();

        shellThread = new Thread(() =>
        {
            proc = new Process
            {
                StartInfo =
                {
                    FileName = GetRunEnv(),
                    Arguments = filePath,
                    CreateNoWindow = false,
                    WindowStyle = ProcessWindowStyle.Normal,
                    UseShellExecute = false,
                    ErrorDialog =  true,
                    RedirectStandardInput = false,
                    RedirectStandardOutput =  true,
                    RedirectStandardError = true,
                    StandardOutputEncoding=Encoding.UTF8,
                    StandardErrorEncoding=Encoding.UTF8
                }
            };

            //输出日志
            proc.OutputDataReceived += (s, e) =>
            {
                string res = Regex.Match(e.Data, " :.*").ToString();
                UnityEngine.Debug.Log((string.IsNullOrEmpty(res) ? e.Data : logcat_filter + res));
            };

            //输出错误信息
            proc.ErrorDataReceived += (s, e) =>
            {
                UnityEngine.Debug.LogError(e.Data);
            };

            proc.Start();
            proc.BeginErrorReadLine();
            proc.BeginOutputReadLine();
            proc.WaitForExit();
        });
        shellThread.Start();
    }

    static string GetRunEnv()
    {
        string exePath = "";
        if(Application.platform == RuntimePlatform.OSXEditor)
        {
            exePath = "/bin/bash";
        }
        else if(Application.platform == RuntimePlatform.WindowsEditor)
        {
            exePath = winGitBashPath;
        }
        else
        {
            UnityEngine.Debug.LogError("Unsupport Platform");
        }
        return exePath;
    }

    static string GetShellFilePath()
    {
        string shPath = "";
        if(Application.platform == RuntimePlatform.OSXEditor)
        {
            shPath = Path.GetFullPath("Packages/rokid.androiddebugtools.unity/Tools/Shell/adb_install_unix.sh");
        }
        else if(Application.platform == RuntimePlatform.WindowsEditor)
        {
            shPath = Path.GetFullPath("Packages/rokid.androiddebugtools.unity/Tools/Shell/adb_install_win.sh");
        }
        else
        {
            UnityEngine.Debug.LogError("Unsupport Platform");
        }

        //UnityEngine.Debug.Log(shPath);

        return shPath;
    }

    private static string GetAdbPath()
    {
        string adbPath = "";
        if(Application.platform == RuntimePlatform.OSXEditor)
        {
            adbPath = Path.GetFullPath("Packages/rokid.androiddebugtools.unity/Tools/Unix");
        }
        else if(Application.platform == RuntimePlatform.WindowsEditor)
        {
            adbPath = Path.GetFullPath("Packages/rokid.androiddebugtools.unity/Tools/Win");
        }
        else
        {
            UnityEngine.Debug.LogError("Unsupport Platform");
        }

        return adbPath;
    }

    /// <summary>
    /// 根据工程更新shell信息
    /// </summary>
    static void UpdateShellFile(bool only_logcat = false)
    {
        UnityEngine.Debug.Log("更新shell");

        GetConfig();

        string shPath = GetShellFilePath();

        string adbPth = GetAdbPath().Replace("\\", "/");

        //加载shell文件
        string adb_content = File.ReadAllText(shPath);

        adb_content = Regex.Replace(adb_content, "port=.*", string.Format("port={0}", adb_port));

        adb_content = Regex.Replace(adb_content, "apk_path_name=.*\"", string.Format("apk_path_name=\"{0}\"", apk_path + "/" + apk_name + ".apk"));

        adb_content = Regex.Replace(adb_content, "pkg_name=.*\"", string.Format("pkg_name=\"{0}\"/\"{1}\"", pkg_name, activity_name));

        adb_content = Regex.Replace(adb_content, "log_filter=.*\"", string.Format("log_filter=\"{0}\"", logcat_filter));

        adb_content = Regex.Replace(adb_content, @"auto_logcat=\d", string.Format("auto_logcat={0}", auto_logcat ? 1 : 0));

        adb_content = Regex.Replace(adb_content, @"only_logcat=\d", string.Format("only_logcat={0}", only_logcat ? 1 : 0));

        adb_content = Regex.Replace(adb_content, @"auto_launch=\d", string.Format("auto_launch={0}", auto_run ? 1 : 0));

        adb_content = Regex.Replace(adb_content, "adb_path=.*\"", string.Format("adb_path=\"{0}\"", adbPth));

        //UnityEngine.Debug.LogWarning(adb_content);

        File.WriteAllText(shPath, adb_content);
    }


    /// <summary>
    /// 更新Shell内容
    /// </summary>
    /// <param name="regex"></param>
    /// <param name="replaceContent"></param>
    /// <param name="shellPath"></param>
    private void UdpateShellContent(string regex, string replaceContent, string shellPath)
    {
        string content = File.ReadAllText(Application.dataPath + "/" + shellPath);
        content = Regex.Replace(content, regex, replaceContent);
        File.WriteAllText(shellPath, content);
    }

    private void OnGUI()
    {
        DrawOptions();
        SaveConfig();
    }

    float pathWidth = 300;
    //绘制插件界面配置项
    private void DrawOptions()
    {

#if UNITY_EDITOR_WIN
        if(string.IsNullOrEmpty(winGitBashPath))
        {
            winGitBashPath = defaultWinGitBashPath;
        }
        GUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("配置GitBash路径:", GUILayout.Width(150));
        winGitBashPath = EditorGUILayout.TextField(winGitBashPath, GUILayout.Width(pathWidth));

        if(GUILayout.Button("配置", GUILayout.Width(50)))
        {
            winGitBashPath = EditorUtility.OpenFolderPanel("选择GitBash路径", winGitBashPath, "");
            EditorGUILayout.TextField(winGitBashPath, GUILayout.Width(150));
        }

        GUILayout.EndHorizontal();
#endif

        GUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Adb Server Port", GUILayout.Width(150));
        adb_port = EditorGUILayout.TextField(adb_port, GUILayout.Width(150));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("ApkName(不包含.apk后缀)", GUILayout.Width(150));
        apk_name = EditorGUILayout.TextField(apk_name, GUILayout.Width(pathWidth));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("请选择打包路径:", GUILayout.Width(150));
        apk_path = EditorGUILayout.TextField(apk_path, GUILayout.Width(pathWidth));

        if(GUILayout.Button("打开", GUILayout.Width(50)))
        {
            apk_path = EditorUtility.OpenFolderPanel("选择导出路径", apk_path, "");
            EditorGUILayout.TextField(apk_path, GUILayout.Width(150));
        }
        GUILayout.EndHorizontal();

        auto_run = GUILayout.Toggle(auto_run, "安装完是否自动运行");

        if(auto_run)
        {
            GUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("运行的活动名", GUILayout.Width(150));
            activity_name = EditorGUILayout.TextField(activity_name, GUILayout.Width(300));
            GUILayout.EndHorizontal();
        }

        auto_logcat = GUILayout.Toggle(auto_logcat, "安装后是否开启logcat");

        if(auto_logcat)
        {
            GUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("请输入logcat的过滤条件", GUILayout.Width(150));
            logcat_filter = EditorGUILayout.TextField(logcat_filter, GUILayout.Width(150));
            GUILayout.EndHorizontal();
        }
    }

    private static void GetConfig()
    {
        TAG = Application.identifier + "_" + typeof(AndroidDebugTools).FullName + "_";

        //初始化信息
        adb_port = EditorPrefs.GetString(TAG + "adb_port", "5555");
        apk_name = EditorPrefs.GetString(TAG + "apk_name", "demo");
        apk_path = EditorPrefs.GetString(TAG + "apk_path", Application.dataPath + "../");
        auto_logcat = EditorPrefs.GetBool(TAG + "auto_logcat", true);
        auto_run = EditorPrefs.GetBool(TAG + "auto_run", true);
        logcat_filter = EditorPrefs.GetString(TAG + "logcat_filter", "Unity");
        activity_name = EditorPrefs.GetString(TAG + "activity_name", "com.unity3d.player.UnityPlayerActivity");
        pkg_name = Application.identifier;
        winGitBashPath = EditorPrefs.GetString(TAG + "winGitBashPath", defaultWinGitBashPath);
    }

    //将配置信息保持到EditorPrefs
    private void SaveConfig()
    {
        EditorPrefs.SetString(TAG + "adb_port", adb_port);
        EditorPrefs.SetString(TAG + "apk_name", apk_name);
        EditorPrefs.SetString(TAG + "apk_path", apk_path);
        EditorPrefs.SetBool(TAG + "auto_logcat", auto_logcat);
        EditorPrefs.SetBool(TAG + "auto_run", auto_run);
        EditorPrefs.SetString(TAG + "activity_name", activity_name);
        EditorPrefs.SetString(TAG + "logcat_filter", logcat_filter);
        EditorPrefs.SetString(TAG + "winGitBashPath", winGitBashPath);
    }

    private void OnApplicationFocus(bool focusStatus)
    {
        UnityEngine.Debug.Log("focus:" + focusStatus);
    }

    private void OnDestroy()
    {
        //保存数据
        SaveConfig();
    }


}